class EC11{
  private:
    int             EC11_A                          = 0;               // 定义引脚A
    int             EC11_B                          = 0;               // 定义引脚B
    int             EC11_S                          = 0;               // 定义按钮引脚
    int             Cycle_steps                     = 0;               // EC11一个周期脉冲数
    int             Position_now                    = 0;               // 当前的位置
    int             Position_last                   = 0;               // 上一次位置
    uint8_t         state                           = 0;               // 0待命，1顺时针旋转中，2逆时针旋转中
    uint8_t         steps                           = 0;               // 记录周期内步数
    unsigned long   presslastMillis                 = 0;               // 按钮被按下时间
    bool            enable                      =  true;               // ec11使能
    bool            pressed                     = false;               // 按钮单次点按事件
    bool            longPressed                 = false;               // 按钮长按事件
    bool            A_BEF                        = true;               // A脚状态，默认上拉高电平
    bool            B_BEF                        = true;               // B脚状态，默认上拉高电平
    bool            S_DEF                        = true;               // 开关引脚状态，默认上拉高电平
    bool            AB_changed                  = false;               // 旋钮事件
    bool            button_pressed              = false;               // 按钮点击事件
    
  public:
    //触发事件
    void            (*CW_Event)();                    // 顺时针旋转一个周期事件
    void            (*CCW_Event)();                   // 逆时针旋转一个周期事件
    void            (*pressingEvent)();               // 按下事件
    void            (*pressedEvent)();                // 短按事件
    void            (*longPressedEvent)();            // 长按事件
    void            (*OperatedEvent)();               // 操作事件，不分类型，不需要使能
    //构造方法
    EC11(int A, int B, int key, int steps){
      EC11_A = A;
      EC11_B = B;
      EC11_S = key;
      Cycle_steps = steps;
    }
    //主循环，监听操作
    bool loop(){
      //旋钮
      if(digitalRead(EC11_A)!=A_BEF||digitalRead(EC11_B)!=B_BEF){
        Position_last = Position_now;
        switch(state){
          case 0:
            if(digitalRead(EC11_A) != A_BEF && digitalRead(EC11_B) == B_BEF){
              Position_now--;
              state = 2;
            }else if(digitalRead(EC11_A) == A_BEF && digitalRead(EC11_B) != B_BEF){
              Position_now++;
              state = 1;
            }
            break;
          case 1:
            Position_now++;
            break;
          case 2:
            Position_now--;
            break;
        }
         steps ++;
        //存储引脚状态
        A_BEF = digitalRead(EC11_A);
        B_BEF = digitalRead(EC11_B);
        //记录步数
        if(steps >= Cycle_steps){
          steps = 0;
          state = 0;
          A_BEF = true;
          B_BEF = true;
          //修正步数，消除抖动
          if(Position_now % Cycle_steps != 0){
            Position_now = Position_now - Position_now % Cycle_steps;
          }
          //旋转一下的处理事项
          if(enable && Position_now - Position_last>0 && CW_Event!=NULL){
            CW_Event();
          }else if(enable && Position_now - Position_last<0 && CCW_Event!=NULL){
            CCW_Event();
          }
        }
        AB_changed = true;
      }else{
        AB_changed = false;
      } 
      //按钮
      if(digitalRead(EC11_S) != S_DEF){
        if(presslastMillis==0){
          presslastMillis = millis();
          if(enable && pressingEvent!=NULL){ pressingEvent(); }
        }else if(millis()-presslastMillis > 2000){         // 长按2s
          longPressed = true;
        }else if(millis()-presslastMillis > 100){         // 短按消抖
          pressed = true;
        }  
        button_pressed = true;
      }else{
        //处理点击事件，优先触发长按事件
        if(enable && longPressed && longPressedEvent != NULL){
          longPressedEvent();
        }else if(enable && pressed && pressedEvent != NULL){
          pressedEvent();
        }
        //恢复参数
        button_pressed = false;
        presslastMillis = 0;
        pressed = false;
        longPressed = false;
      }
      
      //返回操作信息
      if(AB_changed||button_pressed){ 
        if(OperatedEvent!=NULL){ OperatedEvent(); }
        return true; 
      }else{ return false;}
  }

  // 使能
  void eventEnable(bool en){
    enable = en;
  }
  // 返回当前位置
  int getPosition(){
    return Position_now;
  }

  // >0表示顺时针，<0表示逆时针
  int getDirection(){
    return Position_now - Position_last;
  }
  // 旋转事件（顺时针事件，逆时针事件），需要使能
  void addKnobListener(void (*CW_event)(), void (*CCW_event)()){
    CW_Event = CW_event;
    CCW_Event = CCW_event;
  }

  // 按钮按下事件，需要使能
  void add_onPressing_Listener(void (*pressing_Event)()){
    pressingEvent = pressing_Event;
  }
  // 按钮点击事件，，需要使能
  void add_Pressed_Listener(void (*pressed_Event)()){
    pressedEvent = pressed_Event;
  }
  // 按钮长按事件，需要使能
  void add_LongPressed_Listener(void (*longPress_Eeven)()){
    longPressedEvent = longPress_Eeven;
  }
  //一次添加按钮事件，需要使能
  void add_Key_Listener(void (*pressing_Event)(), void (*pressed_Event)(), void (*longPress_Eeven)()){
    pressingEvent = pressing_Event;
    pressedEvent = pressed_Event;
    longPressedEvent = longPress_Eeven;
  }
  // 响应所有操作事件，不需要使能
  void Operated_Listener(void (*event)()){
    OperatedEvent = event;
  }
};
